//@RequireComponent(AudioSource)
// Better disable some scripts if not using them TODO: interrupt dialog
class DialogueGroup{
	var shownSpeech = "";
	var hasEntries : boolean = true;
	var nextDialogue : float = -1; //Indicates end
	var entries : DialogueEntry[];
	var audioEntry : AudioClip;
	var in3dSpace : boolean = true;
	var audioSource : GameObject;
	var sequencer : GameObject;
	var sequenceNumber : int = -1;
	var additionalDuration : float = 0.0;
	var isAdditionalLength : boolean = true; //Additional length or full length
}
class DialogueEntry{
	var shownSpeech = "";
	var nextDialogue = -1;
	var isHidden : boolean = false;
	var functions : DialogueFunction[];
}
class DialogueFunction{
	var theName = "";
	var arguments : float;
	var theTarget : GameObject;
}
enum DialogueState{active, notactive}

var playerCamera : GameObject;
var skin : GUISkin;
var Dialogs : DialogueGroup[];
var activeNum : int = -1;
var titleSize : float = 0.1;
var dialogueSize : float = 40;
//To make player not walking, disable gui etc.
var startFunctions: DialogueFunction[];
var endFunctions: DialogueFunction[];

private var state : DialogueState = DialogueState.notactive;
private var tmpCamera : Transform;
private var isSaid : boolean = false;
private var working : boolean = false;

function OnGUI(){
	if (state == DialogueState.notactive && activeNum == -1)
		enabled = false;
	else if (state == DialogueState.notactive && activeNum != -1){
		//Here we have start of the dialogue
		enabled = true;
		for(fun in startFunctions)
			if(fun.theTarget) fun.theTarget.SendMessage(fun.theName, fun.arguments, SendMessageOptions.DontRequireReceiver);
		state = DialogueState.active;
	} else if(state == DialogueState.active && activeNum != -1){
		GUI.skin = skin;
		GUI.skin.label.alignment = TextAnchor.MiddleCenter;
		GUI.Label (Rect (0, 0, Screen.width, Screen.height*titleSize), Dialogs[activeNum].shownSpeech);
		GUI.skin.label.alignment = TextAnchor.UpperLeft; 
		
		if (Dialogs[activeNum].hasEntries && !working && !isSaid) 
			tellSpeech(false);
		else if(Dialogs[activeNum].hasEntries){
			var amt : int = 0;
			for(var i : int = 0; i<Dialogs[activeNum].entries.length;i++){
				if(!Dialogs[activeNum].entries[i].isHidden && GUI.Button(Rect (Screen.width*0.09, Screen.height-dialogueSize*2-dialogueSize*amt, Screen.width*0.8, dialogueSize), Dialogs[activeNum].entries[Dialogs[activeNum].entries.length-(amt++)-1].shownSpeech)){
					for(fun in Dialogs[activeNum].entries[i].functions)
						if(fun.theTarget) fun.theTarget.SendMessage(fun.theName, fun.arguments, SendMessageOptions.DontRequireReceiver);
					activeNum=Dialogs[activeNum].entries[Dialogs[activeNum].entries.length-i-1].nextDialogue;
					isSaid = false;
				}
			}
		} else if (!working)
			tellSpeech(true);
	} else if (state == DialogueState.active && activeNum == -1){
		//We've got ending;
		for(fun in endFunctions)
			if(fun.theTarget) fun.theTarget.SendMessage(fun.theName, fun.arguments, SendMessageOptions.DontRequireReceiver);
		state = DialogueState.notactive;
	}
}
function tellSpeech(goNext : boolean){//Todo Interrupt audio
	if(!Dialogs[activeNum].in3dSpace || !Dialogs[activeNum].audioSource){
		audio.clip = Dialogs[activeNum].audioEntry;
		audio.loop = false;
		audio.Play();
	} else {
		if(!Dialogs[activeNum].audioSource.GetComponent("AudioSource"))
			Dialogs[activeNum].audioSource.AddComponent("AudioSource");
		Dialogs[activeNum].audioSource.audio.clip = Dialogs[activeNum].audioEntry;
		Dialogs[activeNum].audioSource.audio.loop = false;
		Dialogs[activeNum].audioSource.audio.Play();
	}
	working = true;
	isSaid = true;
	//Camera
	if(activeNum!= -1 && Dialogs[activeNum].sequenceNumber==-1 && Dialogs[activeNum].sequencer){
		playerCamera.transform.position = Dialogs[activeNum].sequencer.transform.position;
		playerCamera.transform.rotation = Dialogs[activeNum].sequencer.transform.rotation;
	} else if (activeNum!= -1 && Dialogs[activeNum].sequencer){
		if(Dialogs[activeNum].sequencer.GetComponent(CameraWaypointCut))
			Dialogs[activeNum].sequencer.GetComponent(CameraWaypointCut).SendMessage("Play", Dialogs[activeNum].sequenceNumber);//,SendMessageOptions.DontRequireReceiver);
		if(Dialogs[activeNum].sequencer.GetComponent(CameraWaypointSmooth))
			Dialogs[activeNum].sequencer.GetComponent(CameraWaypointSmooth).SendMessage("Play", Dialogs[activeNum].sequenceNumber);//,SendMessageOptions.DontRequireReceiver);
	}
	yield WaitForSeconds((Dialogs[activeNum].isAdditionalLength && audio)?audio.clip.length+Dialogs[activeNum].additionalDuration : Dialogs[activeNum].additionalDuration );
	
	if(goNext){ 
		if(Dialogs[activeNum].nextDialogue>=Dialogs.length)
			Debug.Log("Dialogue: The dialogue "+activeNum+" goes out of bounds");
		activeNum = (Dialogs[activeNum].nextDialogue);
		isSaid = false;
	}
	working = false;
}